<template>
  <div class="about">
    <el-form label-width="80px">
      <div>
        <el-form-item label="应用标识">
          {{ appKey }}
        </el-form-item>
      </div>
      <el-form-item label="用户编号">
        {{ userID }}
      </el-form-item>
      <el-form-item label="用户令牌">
        {{ userToken }}
      </el-form-item>
      <el-form-item label="房间编号">
        {{ roomId }}
      </el-form-item>
      <el-form-item label="用户名">
        {{ userName }}
      </el-form-item>
    </el-form>
    <br/>
    <button @click="joinMeeting">进入会议</button>
    <button @click="publishVideo">发布音视频</button>
    <button @click="unpublishVideo">取消发布音视频</button>
    <button @click="publishScreen">发布共享屏幕</button>
    <button @click="unpublishScreen">取消发布共享屏幕</button>
    <button @click="enableAudio">打开音频</button>
    <button @click="disableAudio">关闭音频</button>
    <button @click="enableVideo">打开视频</button>
    <button @click="disableVideo">关闭视频</button>
    <button @click="leaveMeeting">离开会议</button>
    <br/>
    <div style="width: 1500px; height: 720px; position: relative;">
      <video id="currentTrack" style="width: 1280px; height: 100%; border: 1px solid; float: left;"></video>
      <div style="width: 200px; height: 100%; float: right; border: 1px solid;" id="videos_area"></div>
    </div>
    <img :src="imgBase64" alt="">
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { RongIMClient, ConnectionStatus } from '@rongcloud/imlib-v2'

import * as qs from 'querystring'
import {
  installer,
  ISubscribeAttr,
  RCAbstractRoom,
  RCFrameRate,
  RCLocalAudioTrack,
  RCLocalTrack,
  RCRemoteAudioTrack,
  RCRemoteTrack,
  RCRemoteVideoTrack,
  RCResolution,
  RCRTCClient,
  RCRTCCode,
  RCRTCRoom,
  RCTrack
} from '@rongcloud/plugin-rtc'

const electron = window.require('electron')

export default defineComponent({
  name: 'Home',
  data () {
    return {
      appKey: '',
      userID: '',
      userName: '',
      userToken: '',
      roomId: '',
      service: '',
      rtcClient: {} as RCRTCClient,
      room: {} as RCRTCRoom,
      audioTrack: {} as RCLocalTrack,
      videoTrack: {} as RCLocalTrack,
      screenTrack: {} as RCLocalTrack,
      tracks: [] as RCTrack[],

      //
      imgBase64: ''
    }
  },
  mounted () {
    const a = location.hash.replace('#/about?', '')
    const data = qs.parse(a)
    this.appKey = data.appKey as string
    this.userID = data.userID as string
    this.userName = data.userName as string
    this.userToken = data.userToken as string
    this.roomId = data.roomId as string
    this.service = data.service as string
  },
  methods: {
    joinMeeting () {
      // 初始化 IM
      RongIMClient.init(this.appKey, undefined, { navi: this.service })

      // 设置 IM 连接状态监听
      RongIMClient.setConnectionStatusListener({
        onChanged (status: ConnectionStatus) {
          // 连接状态变更通知
          console.log('IM连接状态变更通知', status)
        }
      })

      // eslint-disable-next-line @typescript-eslint/no-this-alias
      const self = this
      // 建立 IM 连接
      RongIMClient.connect(this.userToken, {
        onSuccess (userId: string) {
          // 连接已成功, 可以进行 RTC 相关业务操作
          console.log('建立IM连接成功', userId)

          // 加入房间
          self.joinRoom(self.roomId)
        },
        onTokenIncorrect () {
          // 连接失败，token 无效
          console.log('建立IM连接失败', 'token无效')
        },
        onError: function (errorCode) {
          // 连接失败, 失败原因 -> errorCode);
          console.log('建立IM连接失败', errorCode)
        }
      })
    },
    // 加入房间
    async joinRoom (roomID: string) {
      // 获取 IMLib 的单例实例
      const im = RongIMClient.getInstance()
      // 初始化 RTC
      const rtcClient = im.install(installer, {})
      if (rtcClient == null) {
        console.log('RTC 初始化失败！')
        return
      }
      this.rtcClient = rtcClient

      // 加入普通音视频房间，从 5.0.7 开始增加返回 `tracks` 与 `userIds`
      // * userIds - 当前已加入房间的远端人员列表
      // * tracks  - 当前已发布至房间内的远端资源列表
      const {
        code,
        room,
        userIds,
        tracks: remoteTracks
      } = await rtcClient.joinRTCRoom(roomID)

      // 若加入失败，则 room、userIds、tracks 值为 undefined
      if (code !== RCRTCCode.SUCCESS) {
        console.log('加入房间失败', code)
        return
      }
      if (!room) {
        console.log('加入房间失败', 'room为undefined')
        return
      }
      this.room = room
      console.log('已入会用户编号集合', userIds)
      console.log('已发布远端资源集合', remoteTracks)
      // eslint-disable-next-line @typescript-eslint/no-this-alias
      const self = this

      // 注册房间事件监听器，重复注册时，仅最后一次注册有效
      room.registerRoomEventListener({
        /**
         * 本端被踢出房间时触发
         * @description 被踢出房间可能是由于服务端超出一定时间未能收到 rtcPing 消息，所以认为己方离线。
         * 另一种可能是己方 rtcPing 失败次数超出上限，故而主动断线
         * @param byServer
         * 当值为 false 时，说明本端 rtcPing 超时
         * 当值为 true 时，说明本端收到被踢出房间通知
         */
        onKickOff (byServer: boolean) {
          console.log('本端被踢出房间', byServer ? '本端 rtcPing 超时' : '本端收到被踢出房间通知')
        },
        /**
         * 接收到房间信令时回调，用户可通过房间实例的 `sendMessage(name, content)` 接口发送信令
         * @param name 信令名
         * @param content 信令内容
         * @param senderUserId 发送者 Id
         * @param messageUId 消息唯一标识
         */
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        onMessageReceive (name: string, content: any, senderUserId: string, messageUId: string) {
          console.log('接收到房间信令', name, content, senderUserId, messageUId)
        },
        /**
         * 监听房间属性变更通知
         * @param name
         * @param content
         */
        onRoomAttributeChange (name: string, content: string) {
          console.log('房间属性变更', name, content)
        },
        /**
         * 发布者关闭/启用音频
         * @param audioTrack RCRemoteAudioTrack 类实例
         */
        onAudioMuteChange (audioTrack: RCRemoteAudioTrack) {
          console.log('发布者关闭/启用音频', audioTrack)
        },
        /**
         * 发布者关闭/启用视频
         * @param videoTrack RCRemoteVideoTrack 类实例对象
         */
        onVideoMuteChange (videoTrack: RCRemoteVideoTrack) {
          console.log('发布者关闭/启用视频', videoTrack)
        },
        /**
         * 房间内其他用户新发布资源时触发
         * 如需获取加入房间之前房间内某个用户发布的资源列表，可使用 room.getRemoteTracksByUserId('userId') 获取
         * @param tracks 新发布的音轨与视轨数据列表，包含新发布的 RCRemoteAudioTrack 与 RCRemoteVideoTrack 实例
         */
        async onTrackPublish (tracks: RCRemoteTrack[]) {
          console.log('房间内其他用户新发布资源', tracks)

          // 视频流仅订阅小流，节约带宽
          const subscribeTracks: (RCRemoteTrack | ISubscribeAttr)[] = []
          tracks.forEach(track => {
            if (track.isVideoTrack()) {
              subscribeTracks.push({
                track: track,
                subTiny: true // 订阅小流
              })
            } else {
              subscribeTracks.push(track)
            }
          })
          // 按业务需求选择需要订阅资源，通过 room.subscribe 接口进行订阅
          const { code } = await room.subscribe(subscribeTracks)
          if (code !== RCRTCCode.SUCCESS) {
            console.log('资源订阅失败', code)
          } else {
            console.log('资源订阅成功', code)
          }
        },
        /**
         * 房间用户取消发布资源
         * @param tracks 被取消发布的音轨与视轨数据列表
         * @description 当资源被取消发布时，SDK 内部会取消对相关资源的订阅，业务层仅需处理 UI 业务
         */
        onTrackUnpublish (tracks: RCRemoteTrack[]) {
          // 移除video标签
          self.removeVideo(tracks)
          console.log('房间用户取消发布资源', tracks)
        },
        /**
         * 订阅的音视频流通道已建立, track 已可以进行播放
         * @param track RCRemoteTrack 类实例
         */
        onTrackReady (track: RCRemoteTrack) {
          if (track.isAudioTrack()) {
            // 音轨不需要传递播放控件
            track.play()
          } else {
            // 视轨需要一个 video 标签才可进行播放
            self.bindVideo(track)
          }
        },
        /**
         * 人员加入
         * @param userIds 加入的人员 id 列表
         */
        onUserJoin (userIds: string[]) {
          console.log('加入会议', userIds)
          for (let i = 0; i < userIds.length; i++) {
            self.bindUser(userIds[i], 'video')
          }
        },
        /**
         * 人员退出
         * @param userIds
         */
        onUserLeave (userIds: string[]) {
          console.log('退出会议', userIds)
          for (let i = 0; i < userIds.length; i++) {
            // 移除共享屏幕标签
            self.removeUser(userIds[i], 'screen')
            // 移除视频标签
            self.removeUser(userIds[i], 'video')
          }
        }
      })

      /**
       * 添加音量变化通知
       * @param handler 音量变化通知执行事件
       * @param gap 时间间隔，有效值为 300ms-1000ms，默认为 1000ms
       */
      room.onAudioLevelChange((audioLevelReportList: { track: RCLocalAudioTrack | RCRemoteAudioTrack, audioLevel: number }[]) => {
        console.log('音量变化通知', audioLevelReportList)
      })

      // 创建本地用户并发布音视频
      this.bindUser(this.userID, 'video')
      this.publishVideo()

      // 创建其他用户
      if (userIds && userIds.length >= 1) {
        userIds.forEach(userID => {
          self.bindUser(userID, 'video')
        })
      }

      // 订阅已经存在其他参会者发布的音视轨数据
      if (remoteTracks && remoteTracks.length >= 1) {
        // 视频流仅订阅小流，节约带宽
        const subscribeTracks: (RCRemoteTrack | ISubscribeAttr)[] = []
        remoteTracks.forEach(track => {
          if (track.isVideoTrack()) {
            subscribeTracks.push({
              track: track,
              subTiny: true // 订阅小流
            })
          } else {
            subscribeTracks.push(track)
          }
        })

        const { code } = await room.subscribe(subscribeTracks)
        if (code !== RCRTCCode.SUCCESS) {
          console.log(`资源订阅失败 -> code: ${code}`)
        }
      }
    },
    // 发布音频
    async publishAudio () {
      // 仅当 `code === RCRTCCode.SUCCESS` 时 audioTrack 有值
      // audioTrack 为 RCMicphoneAudioTrack 类型实例
      const {
        code,
        track: audioTrack
      } = await this.rtcClient.createMicrophoneAudioTrack('audio')
      if (code !== RCRTCCode.SUCCESS || !audioTrack) {
        console.log('获取音频失败', code)
        return
      }

      const result = await this.room.publish([audioTrack])
      // 若资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('音频发布失败:', result.code)
      }
    },
    // 取消发布音频
    async unpublishAudio () {
      const tracks = [this.audioTrack as RCLocalTrack]
      const result = await this.room.unpublish(tracks)
      // 若取消资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('取消音频发布失败:', result.code)
        return
      }
      this.audioTrack.destroy()
    },
    // 发布视频
    async publishCamera () {
      // 仅当 `code === RCRTCCode.SUCCESS` 时 videoTrack 有值
      // videoTrack 为 RCCameraVideoTrack 类型实例
      const {
        code,
        track: videoTrack
      } = await this.rtcClient.createCameraVideoTrack('video')
      if (code !== RCRTCCode.SUCCESS || !videoTrack) {
        console.log('获取视频失败', code)
        return
      }

      // 展示本地视频
      this.bindVideo(videoTrack)

      const result = await this.room.publish([videoTrack])
      // 若资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('视频发布失败:', result.code)
        return
      }

      this.videoTrack = videoTrack
    },
    // 取消发布视频
    async unpublishCamera () {
      const tracks = [this.videoTrack as RCLocalTrack]
      const result = await this.room.unpublish(tracks)
      // 若取消资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('取消视频发布失败:', result.code)
        return
      }
      // 移除video标签
      this.removeVideo(tracks)
      this.videoTrack.destroy()
    },
    // 发布音视频
    async publishVideo () {
      // tracks 是一个数组，当 `code !== RCRTCCode.SUCCESS` 时，tracks 长度为 0
      const {
        code,
        tracks
      } = await this.rtcClient.createMicrophoneAndCameraTracks('video')

      if (code !== RCRTCCode.SUCCESS) {
        console.log('获取音视频失败', code)
        return
      }
      // tracks 包含一个 RCMicphoneAudioTrack 实例和一个 RCCameraVideoTrack 实例
      const [audioTrack, videoTrack] = tracks

      // 展示本地视频
      this.bindVideo(videoTrack)

      // 发布音视频流
      // eslint-disable-next-line no-redeclare
      const result = await this.room.publish([audioTrack, {
        track: videoTrack,
        pubTiny: true // pubTiny 用于指定同时发布视频数据的同时，额外发布一个小流数据
      }])

      // 若资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('资源发布失败:', result.code)
        return
      }

      this.audioTrack = audioTrack
      this.videoTrack = videoTrack
    },
    // 取消发布音视频
    async unpublishVideo () {
      const tracks = [this.audioTrack as RCLocalTrack, this.videoTrack as RCLocalTrack]
      const result = await this.room.unpublish(tracks)
      // 若取消资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('取消音视频发布失败:', result.code)
        return
      }
      // 移除video标签
      this.removeVideo(tracks)

      this.audioTrack.destroy()
      this.videoTrack.destroy()
    },
    // 打开音频
    enableAudio () {
      this.audioTrack.unmute()
    },
    // 关闭音频
    disableAudio () {
      this.audioTrack.mute()
    },
    // 打开视频
    enableVideo () {
      this.videoTrack.unmute()
    },
    // 关闭视频
    disableVideo () {
      this.videoTrack.mute()
    },
    // 发布屏幕共享
    async publishScreen () {
      const res = await electron.desktopCapturer.getSources({ types: ['window', 'screen'] })

      this.imgBase64 = res[0].thumbnail.toDataURL()

      // 获取屏幕共享流
      const {
        code,
        track: screenTrack
      } = await this.rtcClient.createScreenVideoTrack('screen', {
        // 默认帧率为 15
        frameRate: RCFrameRate.FPS_10,
        // 默认分辨率为 640 * 480
        resolution: RCResolution.W1920_H1080,
        chromeMediaSourceId: res[0].id
      })

      if (code !== RCRTCCode.SUCCESS || !screenTrack) {
        console.warn('捕获屏幕共享流失败 ->', code)
        return
      }

      // 监听屏幕共享流结束事件, RCLocalTrack 可以通过 import { RCLocalTrack } from '@rongcloud/plugin-rtc' 获取
      // eslint-disable-next-line @typescript-eslint/no-this-alias
      const self = this
      screenTrack.on(RCLocalTrack.EVENT_LOCAL_TRACK_END, (track: RCLocalTrack) => {
        // 取消发布屏幕共享流，room 为当前加入的房间实例
        self.room.unpublish([track])
        // 移除video标签
        self.removeVideo([track])

        self.screenTrack.destroy()
      })

      // 发布屏幕共享流
      const result = await this.room.publish([screenTrack])
      if (result.code !== RCRTCCode.SUCCESS) {
        console.warn('发布屏幕共享流失败 ->', result.code)
        return
      }

      // 展示本地视频
      this.bindVideo(screenTrack)

      this.screenTrack = screenTrack
    },
    // 取消发布屏幕共享
    async unpublishScreen () {
      const tracks = [this.screenTrack as RCLocalTrack]
      const result = await this.room.unpublish(tracks)
      // 若取消资源发布失败
      if (result.code !== RCRTCCode.SUCCESS) {
        console.log('取消屏幕共享发布失败:', result.code)
        return
      }
      // 移除video标签
      this.removeVideo(tracks)

      this.screenTrack.destroy()
    },
    // 离开会议
    async leaveMeeting () {
      // 取消发布音视频
      this.unpublishVideo()
      // 取消发布共享屏幕
      this.unpublishScreen()

      const { code } = await this.rtcClient.leaveRoom(this.room as RCAbstractRoom)
      if (code !== RCRTCCode.SUCCESS) {
        console.log(`离开会议失败 -> code: ${code}`)
      }

      // 移除所有视频及共享屏幕流
      this.tracks.splice(0)
      const currentVideoElement = document.getElementById('currentTrack')
      if (currentVideoElement) {
        currentVideoElement.setAttribute('track-id', '')
      }

      // 移除所有标签
      const videosArea = document.getElementById('videos_area')
      if (!videosArea || !videosArea.hasChildNodes()) {
        return
      }
      for (let i = videosArea.childNodes.length - 1; i >= 0; i--) {
        videosArea.removeChild(videosArea.childNodes[i])
      }
    },
    // 创建用户标签
    bindUser (userID: string, tag: string): HTMLElement | undefined {
      const videosArea = document.getElementById('videos_area')
      if (!videosArea) {
        return
      }

      const videoID = `${tag}_${userID}`
      const divElement = document.createElement('div')
      divElement.id = `div_${videoID}`
      divElement.style.position = 'relative'
      const titleElement = document.createElement('span')
      titleElement.style.position = 'absolute'
      titleElement.style.color = 'red'
      titleElement.style.top = '8px'
      titleElement.style.left = '8px'
      titleElement.style.zIndex = '1'
      titleElement.style.cursor = 'pointer'
      titleElement.innerText = userID
      divElement.append(titleElement)

      // 创建视频流标签
      const videoElement = document.createElement('video')
      videoElement.id = `${videoID}`
      videoElement.style.width = '200px'
      videoElement.onclick = () => {
        const currentVideoElement = document.getElementById('currentTrack')
        if (!currentVideoElement) {
          return
        }
        // 播放视频或共享屏幕流
        let track
        for (let i = 0; i < this.tracks.length; i++) {
          if (`${this.tracks[i].getTag()}_${this.tracks[i].getUserId()}` === videoElement.id) {
            track = this.tracks[i]
            break
          }
        }

        if (track && track.getTrackId() !== currentVideoElement.getAttribute('track-id')) {
          currentVideoElement.setAttribute('track-id', track.getTrackId())
          track.play(currentVideoElement as HTMLVideoElement)
        }
      }
      divElement.append(videoElement)

      if (this.userID === userID && tag === 'video') {
        const audioEnableButton = document.createElement('div')
        audioEnableButton.id = `btn_audio_enable_${videoID}`
        audioEnableButton.style.position = 'absolute'
        audioEnableButton.style.color = 'red'
        audioEnableButton.style.bottom = '8px'
        audioEnableButton.style.right = '8px'
        audioEnableButton.style.zIndex = '1'
        audioEnableButton.style.cursor = 'pointer'
        audioEnableButton.innerText = '关闭音频'
        audioEnableButton.onclick = (event) => {
          if (audioEnableButton.innerText === '启用音频') {
            this.publishAudio()
            audioEnableButton.innerText = '关闭音频'
          } else {
            this.unpublishAudio()
            audioEnableButton.innerText = '启用音频'
          }
          event.stopPropagation()
        }
        divElement.append(audioEnableButton)

        const videoEnableButton = document.createElement('div')
        videoEnableButton.id = `btn_video_enable_${videoID}`
        videoEnableButton.style.position = 'absolute'
        videoEnableButton.style.color = 'red'
        videoEnableButton.style.bottom = '8px'
        videoEnableButton.style.right = '100px'
        videoEnableButton.style.zIndex = '1'
        videoEnableButton.style.cursor = 'pointer'
        videoEnableButton.innerText = '关闭视频'
        videoEnableButton.onclick = (event) => {
          if (videoEnableButton.innerText === '启用视频') {
            this.publishCamera()
            videoEnableButton.innerText = '关闭视频'
          } else {
            this.unpublishCamera()
            videoEnableButton.innerText = '启用视频'
          }
          event.stopPropagation()
        }
        divElement.append(videoEnableButton)
      }

      videosArea.append(divElement)

      return divElement
    },
    // 移除用户标签
    removeUser (userID: string, tag: string) {
      const videoElement = document.getElementById(`div_${tag}_${userID}`)
      if (videoElement) {
        videoElement.remove()
      }
    },
    // 创建并绑定video标签
    bindVideo (track: RCTrack) {
      const videoID = `${track.getTag()}_${track.getUserId()}`
      // 获取用户标签
      let divElement: HTMLElement | null | undefined = document.getElementById(`div_${videoID}`)
      if (!divElement) {
        divElement = this.bindUser(track.getUserId(), track.getTag())
      }
      if (!divElement) {
        return
      }

      // 获取video标签
      const videoElement = document.getElementById(videoID)
      // 若video标签存在，则绑定视频流
      if (videoElement) {
        track.play(videoElement as HTMLVideoElement)
        this.pushTrack(track)
      }

      // 若非用户本身视频及共享屏幕流，则不添加操作按钮
      if (this.userID !== track.getUserId()) {
        return
      }

      // eslint-disable-next-line @typescript-eslint/no-this-alias
      const self = this
      // 创建操作按钮，仅用户本身视频及共享屏幕才添加操作按钮
      if (track.getTag() === 'video') {
        const audioEnableButtonID = `btn_audio_enable_${videoID}`
        const audioEnableButtonElement = document.getElementById(audioEnableButtonID)
        if (!audioEnableButtonElement) {
          const audioEnableButton = document.createElement('div')
          audioEnableButton.id = audioEnableButtonID
          audioEnableButton.style.position = 'absolute'
          audioEnableButton.style.color = 'red'
          audioEnableButton.style.bottom = '8px'
          audioEnableButton.style.right = '8px'
          audioEnableButton.style.zIndex = '1'
          audioEnableButton.style.cursor = 'pointer'
          audioEnableButton.innerText = '关闭音频'
          audioEnableButton.onclick = (event) => {
            if (audioEnableButton.innerText === '启用音频') {
              self.publishAudio()
              audioEnableButton.innerText = '关闭音频'
            } else {
              self.unpublishAudio()
              audioEnableButton.innerText = '启用音频'
            }
            event.stopPropagation()
          }
          divElement.append(audioEnableButton)
        }

        const videoEnableButtonID = `btn_video_enable_${videoID}`
        const videoEnableButtonElement = document.getElementById(videoEnableButtonID)
        if (!videoEnableButtonElement) {
          const videoEnableButton = document.createElement('div')
          videoEnableButton.id = videoEnableButtonID
          videoEnableButton.style.position = 'absolute'
          videoEnableButton.style.color = 'red'
          videoEnableButton.style.bottom = '8px'
          videoEnableButton.style.right = '100px'
          videoEnableButton.style.zIndex = '1'
          videoEnableButton.style.cursor = 'pointer'
          videoEnableButton.innerText = '关闭视频'
          videoEnableButton.onclick = (event) => {
            if (videoEnableButton.innerText === '启用视频') {
              self.publishCamera()
              videoEnableButton.innerText = '关闭视频'
            } else {
              self.unpublishCamera()
              videoEnableButton.innerText = '启用视频'
            }
            event.stopPropagation()
          }
          divElement.append(videoEnableButton)
        }
      } else if (track.getTag() === 'screen') {
        const screenDisableButton = document.createElement('div')
        screenDisableButton.style.position = 'absolute'
        screenDisableButton.style.color = 'red'
        screenDisableButton.style.bottom = '8px'
        screenDisableButton.style.right = '8px'
        screenDisableButton.style.zIndex = '1'
        screenDisableButton.style.cursor = 'pointer'
        screenDisableButton.innerText = '停止共享'
        screenDisableButton.onclick = (event) => {
          self.unpublishScreen()
          event.stopPropagation()
        }
        divElement.append(screenDisableButton)
      }
    },
    // 移除video标签
    removeVideo (tracks: RCTrack[]) {
      for (let i = 0; i < tracks.length; i++) {
        this.removeTrack(tracks[i])
        // 若为共享屏幕，则直接移除标签
        if (tracks[i].getTag() === 'screen') {
          this.removeUser(tracks[i].getUserId(), tracks[i].getTag())
        }
      }
    },
    // 添加视频或共享屏幕流
    pushTrack (track: RCTrack) {
      const trackIndex = this.tracks.findIndex(item => item.getTrackId() === track.getTrackId())
      // 若已存在，则不添加
      if (trackIndex >= 0) {
        return
      }

      this.tracks.push(track)
      this.bindDefaultTrack()
    },
    // 移除视频或共享屏幕流
    removeTrack (track: RCTrack) {
      const trackIndex = this.tracks.findIndex(item => item.getTrackId() === track.getTrackId())
      // 若不存在，则不移除
      if (trackIndex === -1) {
        return
      }

      this.tracks.splice(trackIndex, 1)
      this.bindDefaultTrack(track.getTrackId())
    },
    // 绑定默认展示视频或共享屏幕流
    bindDefaultTrack (trackID?: string) {
      const currentVideoElement = document.getElementById('currentTrack')
      if (!currentVideoElement) {
        return
      }

      if (this.tracks.length <= 0) {
        currentVideoElement.setAttribute('track-id', '')
        return
      }

      const currentTrackID = currentVideoElement.getAttribute('track-id')
      // 若已赋值且当前轨非移除项，则不进行重新赋值
      if (currentTrackID && currentTrackID !== trackID) {
        return
      }

      const track = this.tracks[0]
      currentVideoElement.setAttribute('track-id', track.getTrackId())
      track.play(currentVideoElement as HTMLVideoElement)
    }
  }
})
</script>
